package bmaso.purest.castor;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;

import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;

public class UnmarshalTag extends BodyTagSupport {

	private PageContext pc;
	private String mappingResourceName = null;
	private String varName = "unmarshalledObject";
	private Object unmarshalled = null;
	private Class<?> clazz = null;
	private int scopeValue = PageContext.PAGE_SCOPE;
	
	@Override
	public int doEndTag() throws JspException {
		try {
			if(getMappingResource() == null) {
				unmarshalled = Unmarshaller.unmarshal(clazz, pc.getRequest().getReader());
				pc.setAttribute(varName, unmarshalled, scopeValue);
			}
			
			return SKIP_BODY;
		} catch(IOException ioe) {
			throw new JspException(ioe);
		} catch(ValidationException ve) {
			throw new JspException(ve);
		} catch(MarshalException me) {
			throw new JspException(me);
		}
	}
	
	
	@Override
	public void release() {
		super.release();
		mappingResourceName = null;
		unmarshalled = null;
	}

	public void setPageContext(PageContext pc) {
		super.setPageContext(pc);
		this.pc = pc;
	}
	
	public void setMappingResource(String mappingResourceName) {
		this.mappingResourceName = mappingResourceName;
	}
	
	public String getMappingResource() {
		return mappingResourceName;
	}
	
	public String getUnmarshalClass() {
		return clazz.getName();
	}
	
	public void setUnmarshalClass(String clazz) {
		try {
			this.clazz = Class.forName(clazz);
		} catch(ClassNotFoundException cnfe){
			throw new IllegalArgumentException(cnfe);
		}
	}
	
	public void setVar(String varName) {
		this.varName = varName;
	}
	
	public String getVar() {
		return varName;
	}
	
	public String getScope() {
		switch(scopeValue) {
		case PageContext.PAGE_SCOPE: return "page";
		case PageContext.REQUEST_SCOPE: return "request";
		case PageContext.SESSION_SCOPE: return "session";
		case PageContext.APPLICATION_SCOPE: return "application";
		default: 
			//...should never happen...
			return null;
		}
	}
	
	public void setScope(String scope) {
		if("page".equals(scope)) { scopeValue = PageContext.PAGE_SCOPE; }
		else if("request".equals(scope)) { scopeValue = PageContext.REQUEST_SCOPE; }
		else if("session".equals(scope)) { scopeValue = PageContext.SESSION_SCOPE; }
		else if("application".equals(scope)) { scopeValue = PageContext.APPLICATION_SCOPE; }
		else {
			throw new IllegalArgumentException(scope + " is not a valid variable scope. Use one of \"page\" (default), \"request\", \"session\", or \"application\"");
		}
	}
}
